home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
unixlib.lha
/
unix
/
unix.doc
< prev
next >
Wrap
Text File
|
1996-12-01
|
16KB
|
404 lines
Unix compatibility library for SAS/C 6.55+
------------------------------------------
Note: this is an edited version of the original doc written by David Gay
to reflect the changes I introduced.
Introduction
------------
This library provides 110+ odd functions which are useful for porting
Unix programs to the Amiga running AmigaDOS 2.04 or higher. It is thus
similar to ixemul.library, but has more restricted aims:
a) It is written specifically for SAS/C 6.55+.
b) It isn't a complete C library, it requires the SAS/C library to function.
It adds some routines, and replaces others that were deficient, out of date,
or that didn't provide adequate functionality.
c) It isn't a complete Unix emulation library, it only contains those functions
that I needed while porting various utilities (mainly from GNU) to the Amiga.
d) It is a traditional C link library, not an Amiga library. This produces
bigger executables.
Considering the above points, you might ask why David wrote it ...
There are several good answers:
a) He started it before he was aware of ixemul.library.
b) ixemul.library didn't provide the features he needed for Emacs (support for
select).
c) It was easier for him to maintain when he found the need to support another
Unix feature (eg deleting open files).
As regard me, I updated it to SAS/C 6.55+ and added other improvements to
be able to port X11 programs to AmiWin.
Copying
-------
The library includes code that David (and I) have written, which he (and I)
place in the public domain. This is found in all the files that don't have a
Copyright notice.
It also includes code which is (inclusive of my modifications)
Copyright (c) 1982, 1986, 1991 The Regents of the University of California.
All rights reserved.
This code is freely redistributable (see the copyright notices in the source
and include files).
Finally it includes Stefan Proels's public domain alloca implementation
specifically written for SAS/C 6.55+.
Installation & Use
------------------
To use this library, you must compile with the include directory in your
include search path, and link with the unix.lib library (which must be
specified before sc.lib). For example, if you extract this archive in a
directory called src: and assign uinclude: to src:unix/include and
ulib: to src:unix, you could compile the following program:
echo.c:
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int i;
for (i = 1; i < argc; i++) {
if (i != 1) write(1, " ", 1);
write(1, argv[i], strlen(argv[i]));
}
write(1, "\n", 1);
return 0;
}
with the command
sc link idir=uinclude: lib=ulib:unix.lib echo.c
to produce a simple unix-like echo command.
Among other improvements, I added support for sockets code, relying for this
on AmiTCP's bsdsocket.library. If you need compiling code containing socket
calls, than you should have AmiTCP, its include files in netinclude: and
1) compile with AMITCP defined (DEF=AMITCP)
2) add netinclude: AFTER uinclude: in the include search path
3) have an #include <proto/socket.h> in your code
So the command to compile prog.c (containing socket calls) should be like
sc link DEF=AMITCP idir=uinclude: idir=netinclude: lib=ulib:unix.lib prog.c
Of course, for compiling code containing socket calls, you could instead use
net.lib, the link library distributed with AmiTCP, but it lacks support for
pipes, i.e. the pipe() call. This unix.lib does not have the complete
functionality of net.lib as regard socket code support but I think it is
sufficient for compiling the vast majority of programs using network sockets.
You should define the following environment variables:
USER - A user name for the sole Amiga user (default "user").
USERNAME - The full name of the sole Amiga user (default $USER).
HOME - A "home" directory (default "s:") for programs that want one.
Configuration files will probably end up here ...
SHELL - A program which behaves reasonably like a Unix shell
(default "bin:sh"). You should copy the sh executable there if
you don't have a Unix-like shell.
HOSTNAME - The name of your machine (default "amiga").
If you are going to be using pipes, you will require Matt Dillon's fifo.library
and fifo: device. This can be found on the Fish disks, with his UUCP
distribution and on any Aminet site.
If you use the popen() and pclose() calls you also need the APipe-Handler.
Again you can find it on any Aminet site.
If you want to install the timezone information (see the discussion below on
Unix vs Amiga time), do the following:
a) change to the zoneinfo directory
b) compile the zic program by running smake.
c) change to the datfiles directory.
d) edit smakefile and choose your timezone (you can look at the data files
to see the ones available). If you get this wrong, you can always change
it later with the zic program.
e) type 'smake install'. This will compile the timezones, and setup the one
you chose as the default. The default can be changed with
zic -l <timezone name>
or by defining the environment variable TZ.
Functionality
-------------
While this library aims to hide the differences between AmigaDOS & Unix,
it also aims to provide support for Amiga specific features. This sometimes
produces strange compromises.
This library provides two things to programs linked with it:
a) A Unix-like environment:
This includes:
- Unix-like command line parsing, with wildcard expansion. These
wildcards are however specified with the Amiga syntax.
Arguments which are unquoted or surround with single quotes are
handled like Unix shells. Those surrounded with double quotes are
handled in the Amiga fashion, but with wildcard expansion (this is
done to avoid problems with the way the exec function works).
Here is a summary of argument splitting:
Arguments can be enclosed in single quotes, (') double quotes ("), or
separated by spaces.
Arguments enclosed by single quotes never suffer wildcard expansion, and
no character is significant inside them (not even \). Given the echo program
given above,
echo 'f*un\'
simply displays
f*un\
Within double quotes, * is the standard Amiga escape character. \ is
handled just like any other character. Wildcards are expanded. So,
assuming the current directory contains only echo.c and echo,
echo "#?.c" "*.c" "\mad"
displays
echo.c .c \mad
(* escapes the following character, except that *N is newline and *E is
escape. Wildcard characters still behave as usual (' is the standard
Amiga wildcard escape character)).
If an argument is unquoted, \ acts as an escape character (removing
special significance from the next character, be it a wildcard, a space,
a \, ...). So
echo \*.c \\ \n
displays
*.c \ n
- When a program is run from the Workbench, stdin, stdout & stderr are
opened on NIL:, and the icons selected are converted to file names and
passed as the argc,argv to main.
- The standard variable environ is defined and contains all the local
environment variables. This is passed as the envp parameter to main.
- The program is led to believe that all files belong to $USER (uid 1),
group wheel (gid 0).
- Amiga protection flags are mapped onto the standard 12 Unix protection
bits (and back when necessary). This can be overridden (dynamically) by
changing the value of use_amiga_flags. Eg:
extern int use_amiga_flags;
...
main()
{
use_amiga_flags = 1;
... some code using stat or chmod or ...
}
In this case, the Amiga protection bits are left untouched. Otherwise the
mapping is as follows (note that the archive bit is lost):
Unix -> Amiga
Amiga read: if user, group or world read.
Amiga write: if user or group write.
Amiga delete: if user or world write.
Amiga execute: if group execute or only user execute.
Amiga script: if world execute or only user execute.
Amiga pure: if sticky.
Amiga -> Unix
user, group, world read: if amiga read.
user write: if amiga write and delete.
group write: if amiga write.
world write: if amiga delete.
user execute: if amiga execute or amiga script.
group execute: if amiga execute.
world execute: if amiga script.
sticky: if amiga pure.
- Unix-like time. time is expressed in seconds since 1-Jan-1970 00:00 GMT.
This is the format used by the time(), stat() and utime() functions. The
library uses the BSD time functions which properly handle timezones,
daylight savings time, etc.
On Unix systems, time is generally stored as GMT, while the Amiga stores
local time. These times are visible in two places: the time stored in the
system clock and the creation, modification or access dates for files
(only the modification date is available on the Amiga). There are 3 ways
to resolve this conflict:
1) Ignore timezones (you can choose this option by not installing the
timezone information). The library will then assume that system time
and file times are expressed in GMT and will never apply any
corrections. All will work well (except maybe on a global network).
This is the simplest solution.
2) System & file time are assumed to be local times. The time() & stat()
functions convert local time to GMT, the utime() call converts GMT to
local time. This allows you to keep the system clock on local time,
which is compatible with most (all?) Amiga applications. However,
nearly every program will be bigger because they will need the timezone
information and timezone conversion code (approximately 7k). The
library can be recompiled if you prefer to have things this way by
adding `DEF USE_LOCAL=1' to the DEFS variable in smakefile.
3) System & file time are stored in GMT. Times are converted to local time
only when they are displayed to the user, who must of course choose the
correct timezone. This entails changing your system clock to GMT, which
means that most programs will display an incorrect time. However, you
won't have to change your system clock when daylight savings time ends.
The library comes compiled this way (But you can still choose option 1,
no timezone information, and avoid the potential confusion).
- BSD-like signals. Signal handlers stay enabled after a signal occurs
(that particular signal is simply masked for the duration of the handler).
setjmp & longjmp preserve the signal mask (the functions _setjmp & _longjmp
don't). You may receive any signal with kill(getpid(), sig). Otherwise only
the following occur:
SIGINT: user typed ctrl-c
SIGQUIT: user typed ctrl-d
SIGALRM: alarm() expired
SIGCHLD: a child process died
SIGIO: asynhronous I/O is pending | these can be triggered only by
SIGURG: urgent data is pending | bsdsocket.library
When using kill to signal another process, only SIGHUP, SIGINT, SIGQUIT &
SIGKILL do anything. They all send SIGBREAKF_CTRL_C | D to the process (and
hopefully its children). See the discussion under the exec function.
b) A large number of unix C library calls:
_exit, _setjmp, _longjmp, abort, alarm, access, alloca, bcmp, bcopy, bzero,
chmod, chown, fchown, close, creat, dup, dup2, fnmatch, getopt, tzset,
tzsetwall, gettimeofday, ftime, localtime, gmtime, asctime, ctime, mktime,
endgrent, endpwent, getgrent, setgid, setegid, setgroupent, setgrent,
setuid, seteuid, opendir, closedir, readdir, telldir, seekdir, fchmod,
fcntl, fstat, ftruncate, getenv, setenv, gethostname, getpid, getwd, getgid,
getegid, getgrgid, getgrnam, hypot, index, ioctl, isatty, kill, link, lseek,
lstat, mkdir, mkfifo, mknod, mktemp, open, perror, pipe, socketpair,
getpwuid, getpwnam, getlogin, popen, pclose, read, readlink, regerror,
regcomp, regexec, regsub, remove, rename, rindex, rmdir, select, setjmp,
longjmp, signal, sigpause, sigprocmask, sigsetmask, sleep, stat, strcasecmp,
strncasecmp, strerror, strftime, symlink, tempnam, time, truncate, getuid,
geteuid, umask, unlink, utime, wait, waitpid, wait3, wait4, write
These functions aim to be BSD compatible, however I based myself on
descriptions in the SunOS 4 man pages. Their behaviour is sometimes strange
or incomplete.
Here is a summary of the differences with the standard Unix functions:
alloca - This is Stefan Proels's alloca for SAS/C. It is implemented taking
advantage of the compiler's PROFILEing facility. If you compile
with the PROFILE switch turned on the compiler calls _PROLOG()
whenever a function is entered and _EPILOG() when the function
returns respectively. Refer to your SAS/C manuals for details.
This alloca() implementation uses those hooks to track alloca()ted
memory. Whenever a function returns all memory alloca()ted by that
function will be freed. Remember to compile with the PROFILE switch
the modules using alloca() if you want a working alloca(). If you
include alloca.h (which you have to do if you want its prototype)
you will be remembered of this ...
gettimeofday - The dst field of the timezone is a (not very good) guess. It
shouldn't be used anyway.
chown, fchown - These are do-nothing routines.
opendir, closedir, ... - These interact with stat to avoid having to read
each directory entry twice when doing a readdir + stat loop.
fchmod - The protection is only set when the file is closed. See also the
discussion of protection modes above.
fcntl - Only the F_GETFL & F_SETFL operations are supported.
truncate, ftruncate - These will not necessarily work with all filing
systems. See the discussion of the AmigaDOS SetFileSize function.
getenv - This checks local environment variables and then global ones. It
allocates memory for the variables value each time. This memory is
never freed (till the program exits).
gethostname - This is obtained from the HOSTNAME environment variable at
startup.
getuid, geteuid, getgid, getegid, getpwuid, getpwnam, getgrgid, getgrnam,
getlogin - These function only know about one user. He/She is:
name: $USER (default "user")
home directory: $HOME (default "s:")
shell: $SHELL (default "bin:sh")
uid: 1, gid: 0
ioctl - Only FIONBIO & TIOCGWINSZ are known (for sockets all those
recognized by AmiTCP), plus a number of amiga specific ioctls
(for internal use). These are documented in include/amiga/ioctl.h.
lseek - Seeks beyond the end of a file are not implemented.
mkfifo, mknod - These are 'do-nothing' routines.
select - This implementation cannot detect 'exceptional' conditions
with pipes & sktpairs. By default FD_SETSIZE is 64. If you need
a large value you must #define FD_SETSIZE before including
<sys/types.h> and, if you use sockets, also set the external
variable _fd_setsize to the same value, e.g.:
#define FD_SETSIZE 128
#include <sys/types.h>
long _fd_setsize = FD_SETSIZE; /* only needed for sockets */
umask - This is a 'do-nothing' routine.
unlink - You can unlink a file that your program has opened before you close
it. At that point, the AmigaDOS file is closed & deleted, though it
still appears open to read (it returns EOF), write, close, etc.
Also you can unlink a file even if it is protected from deletion
(the protection mode is changed first ...).
utime - Only the modification time can be changed (the others don't exist).
wait3, wait4 - Resource usage is never returned.
Recompiling
-----------
To recompile, simply run smake in the src directory. You can add DEF=USE_LOCAL
to DEFS in smakefile if you want the system clock to store local time
instead of GMT.